package com.ruoyi.web.controller.business.order.factory;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.business.base.PageParam;
import com.ruoyi.business.customer.domain.JbCustomer;
import com.ruoyi.business.customer.service.JbCustomerService;
import com.ruoyi.business.order.domain.JbRefund;
import com.ruoyi.business.order.domain.JbRefundCommondity;
import com.ruoyi.business.order.service.JbRefundCommondityService;
import com.ruoyi.business.order.service.JbRefundService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.web.controller.business.goods.factory.JbCommodityFactory;
import com.ruoyi.web.controller.business.order.vo.JbAuditStatusEnum;
import com.ruoyi.web.controller.business.order.vo.JbRefundVO;
import com.ruoyi.web.controller.flyflow.factory.FlyFlowFactory;
import com.ruoyi.web.controller.flyflow.util.FlyFlowUtil;
import com.ruoyi.web.controller.system.factory.SysDataScopeFactory;
import com.ruoyi.web.controller.thirdparty.factory.ThirdpartyOrderFactory;
import com.ruoyi.web.controller.tool.JoCodeUtils;
import com.ruoyi.web.core.JoController;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;

import java.io.IOException;
import java.util.*;

/**
 * 业务 退货工厂
 *
 * @author Jyl
 */
@Log4j2
@Component
public class JbRefundFactory extends JoController
{

    @Autowired
    private JbRefundService service;
    @Autowired
    private JbCustomerService jbCustomerService;
    @Autowired
    private JbRefundCommondityService jbRefundCommondityService;
    @Autowired
    private JbApprovalLogFactory jbApprovalLogFactory;
    @Autowired
    private FlyFlowFactory factory;
    @Autowired
    private JbCommodityFactory jbCommodityFactory;
    @Autowired
    private ThirdpartyOrderFactory thirdpartyOrderFactory;
    @Autowired
    private SysDataScopeFactory sysDataScopeFactory;

    /**
     * @param page     分页
     * @param jbRefund 业务对象
     * @return 查询对象
     */
    public QueryWrapper getQuer(PageParam page, JbRefund jbRefund)
    {
        List<Long> ids = sysDataScopeFactory.fnListDataScope(null);
        QueryWrapper<JbRefund> select = new QueryWrapper<>();
        select.lambda().eq(StringUtils.isNotEmpty(jbRefund.getApprovalStatus()), JbRefund::getApprovalStatus,
                        jbRefund.getApprovalStatus())
                .eq(ObjectUtil.isNotEmpty(jbRefund.getRefundType()), JbRefund::getRefundType, jbRefund.getRefundType())
                .ge(StringUtils.isNotEmpty(page.getStartTime()), JbRefund::getSubmissionTime, page.getStartTime())
                .le(StringUtils.isNotEmpty(page.getEndTime()), JbRefund::getSubmissionTime, page.getEndTime())
                .eq(StringUtils.isNotEmpty(jbRefund.getBusinessManager()), JbRefund::getBusinessManager,
                        jbRefund.getBusinessManager())
                .eq(ObjectUtil.isNotEmpty(jbRefund.getCustomerId()), JbRefund::getCustomerId, jbRefund.getCustomerId())

                .in(ObjectUtil.isNotEmpty(ids), JbRefund::getCreateBy, ids);//数据权限过滤
        ;
        select.orderBy(StringUtils.isNotEmpty(page.getSortKey()), page.isSort(), page.getSortKey());

        return select;
    }

    /**
     * 查询退款列表
     */
    public IPage<JbRefund> list(PageParam page, JbRefund jbRefund)
    {
        IPage<JbRefund> iPage = service.page(page.b(), getQuer(page, jbRefund));
        return iPage;
    }

    /**
     * 新增
     *
     * @param jbRefundVO 退款VO
     * @return
     */
    @Transactional
    public boolean add(JbRefundVO jbRefundVO)
    {
        jbRefundVO.setApprovalStatus(JbAuditStatusEnum.task1.getKey());
        List<JbRefundCommondity> list = jbRefundVO.getCommondityList();
        JbRefund jbRefund = new JbRefund();
        BeanUtils.copyProperties(jbRefundVO, jbRefund);

        JbCustomer jbCustomer = jbCustomerService.getById(jbRefundVO.getCustomerId());
        if (null == jbCustomer)
        {
            log.error("bus:Refund:退货客户没找到");
            return false;
        }

        jbRefund.setCustomerName(jbCustomer.getCustomerName());
        jbRefund.setRefundNumber(JoCodeUtils.CODE().REFUND);
        jbRefund.setSubmitterId(getUserId());
        jbRefund.setSubmitterName(getNickName());
        jbRefund.setSubmissionTime(new Date());

        service.save(jbRefund);

        for (JbRefundCommondity jbRefundCommondity : list)
        {
            jbRefundCommondity.setRefundId(jbRefund.getId());
            jbRefundCommondity.setCustomerId(jbRefundVO.getCustomerId());
            jbRefundCommondity.setCommondityTcode(
                    jbCommodityFactory.getInfo(jbRefundCommondity.getCommondityId()).getCommodityCode()
            );
        }
        jbRefundCommondityService.saveBatch(list);

        startProcess(jbRefund);
        return true;
    }

    /**
     * 更新
     *
     * @param processNumber
     * @param id
     */
    public void updateProcessNumber(String processNumber, Long id)
    {
        service.update(new LambdaUpdateWrapper<JbRefund>()
                .eq(JbRefund::getId, id)
                .set(JbRefund::getProcessNumber, processNumber));
    }

    /**
     * 启动流程实例
     *
     * @param jbRefund
     */
    @Transactional
    public void startProcess(JbRefund jbRefund)
    {
        //处理业务对象
        JSONObject order = JSONObject.parseObject(JSONObject.toJSONString(jbRefund));
        //获取流程
        JSONObject flow = FlyFlowUtil.getProcessInstance(factory.getProcessInstance(), "退货退款审批");
        //获取启动表单
        JSONObject flowInfo = factory.getProcessInstanceInfo(flow.getString("flowId"));

        //构建启动对象
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("uniqueId", flow.getString("uniqueId"));
        jsonObject.put("flowId", flow.getString("flowId"));
        jsonObject.put("paramMap", FlyFlowUtil.buildParamMap(flowInfo, order));
        JSONObject re = factory.processInstanceStart(jsonObject);
        if (!re.getBoolean("ok")) throw new RuntimeException("refund process start fail");

        updateProcessNumber(re.getString("data"), jbRefund.getId());
        jbApprovalLogFactory.saveApprovalLog(
                "refund",
                jbRefund.getRefundNumber(),
                re.getString("data"),
                "发起审批",
                "提交退货退款",
                "提交成功"
        );
    }

    /**
     * 编辑
     *
     * @param jbRefundVO 退款vo
     * @return
     */
    @Transactional
    public boolean edit(JbRefundVO jbRefundVO)
    {
        List<JbRefundCommondity> list = jbRefundVO.getCommondityList();
        JbRefund jbRefund = new JbRefund();
        BeanUtils.copyProperties(jbRefundVO, jbRefund);

        service.updateById(jbRefund);

        List<Long> ids = new ArrayList<>();
        for (JbRefundCommondity jbRefundCommondity : list)
        {
            if (jbRefundCommondity.getId() != null) ids.add(jbRefundCommondity.getId());
            jbRefundCommondity.setRefundId(jbRefund.getId());
            jbRefundCommondity.setCustomerId(jbRefundVO.getCustomerId());
            jbRefundCommondity.setCommondityTcode(
                    jbCommodityFactory.getInfo(jbRefundCommondity.getCommondityId()).getCommodityCode()
            );
        }

        jbRefundCommondityService.remove(new LambdaQueryWrapper<JbRefundCommondity>()
                .eq(JbRefundCommondity::getRefundId, jbRefund.getId())
                .notIn(!ids.isEmpty(), JbRefundCommondity::getId, ids)
        );
        jbRefundCommondityService.saveOrUpdateBatch(list);

        return true;
    }

    /**
     * 获取退款详细信息
     */
    public JbRefundVO getInfo(String number)
    {
        JbRefund jbRefund = service.getOne(new LambdaQueryWrapper<JbRefund>().eq(JbRefund::getRefundNumber, number));
        JbRefundVO jbRefundVO = new JbRefundVO();
        BeanUtils.copyProperties(jbRefund, jbRefundVO);

        jbRefundVO.setCommondityList(jbRefundCommondityService.list(new LambdaQueryWrapper<JbRefundCommondity>()
                .eq(JbRefundCommondity::getRefundId, jbRefund.getId())));
        return jbRefundVO;
    }

    /**
     * 获取退款详细信息
     */
    public JbRefundVO getInfo(Long id)
    {
        JbRefund jbRefund = service.getById(id);
        JbRefundVO jbRefundVO = new JbRefundVO();
        BeanUtils.copyProperties(jbRefund, jbRefundVO);

        jbRefundVO.setCommondityList(jbRefundCommondityService.list(new LambdaQueryWrapper<JbRefundCommondity>()
                .eq(JbRefundCommondity::getRefundId, id)));
        return jbRefundVO;
    }

    /**
     * 删除退款
     */
    public boolean remove(@PathVariable Long[] ids)
    {
        for (Long id : ids)
            jbRefundCommondityService.remove(new LambdaQueryWrapper<JbRefundCommondity>()
                    .eq(JbRefundCommondity::getRefundId, id));
        return service.removeByIds(Arrays.asList(ids));
    }

    /**
     * 同步第三方信息
     *
     * @param jbRefundVO 退货退款单对象
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    public String tNumberUpdate(JbRefundVO jbRefundVO) throws IOException, InterruptedException
    {
        String bizCode = jbRefundVO.getRefundNumber();
        JbRefundVO vo = getInfo(bizCode);
        vo.setTnumber(jbRefundVO.getTnumber());

        Map<String, JSONObject> map = thirdpartyOrderFactory.queryOrder(jbRefundVO.getTnumber(), bizCode);

        for (JbRefundCommondity jbRefundCommondity : vo.getCommondityList())
        {
            if (map.containsKey(jbRefundCommondity.getCommondityTcode()))
            {
                JSONObject jsonObject = map.get(jbRefundCommondity.getCommondityTcode());
                jbRefundCommondity.setCommondityName(jsonObject.getString("inventoryName"));
                jbRefundCommondity.setCommondityBatch(jsonObject.getString("batch"));
                jbRefundCommondity.setCommondityCount(jsonObject.getString("quantity"));
                jbRefundCommondityService.updateById(jbRefundCommondity);
            }
        }
        return "";
    }

    /**
     * 查询 根据流程主键获取 业务详情
     *
     * @param processInstanceId 流程实例主键
     * @return 业务详情
     */
    public JbRefund getInfoByProcessNumber(String processInstanceId)
    {
        return service.getOne(new LambdaQueryWrapper<JbRefund>().eq(JbRefund::getProcessNumber, processInstanceId));
    }

    /**
     * 更新 业务状态
     *
     * @param id     业务主键
     * @param status 业务状态
     * @return 执行结果
     */
    public Boolean updataBusinessStatus(Long id, String status)
    {
        return service.update(new LambdaUpdateWrapper<JbRefund>()
                .eq(JbRefund::getId, id)
                .set(JbRefund::getApprovalStatus, status)
        );
    }
}
